home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / networking / arpsample / arpsampleshell.c < prev    next >
Encoding:
Text File  |  2000-06-23  |  13.6 KB  |  510 lines

  1. /*
  2.     File:        ARPSampleShell.c
  3.  
  4.     Contains:    Sample that shows how to talk to the ARP module.
  5.  
  6.     Written by: Quinn "The Eskimo!"    
  7.  
  8.     Copyright:    Copyright © 1997-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 7/21/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 
  21.  
  22. */
  23. ///////////////////////////////////////////////////////////////////
  24. // Lots of standard OT constructs.
  25.  
  26. #include <OpenTptClient.h>
  27. #include <OpenTptInternet.h>
  28. #include <Memory.h>
  29.  
  30. ///////////////////////////////////////////////////////////////////
  31. // This sample makes heavy use of C's standard I/O package.
  32.  
  33. #include <stdio.h>
  34.  
  35. ///////////////////////////////////////////////////////////////////
  36. // Standard C string operations.
  37.  
  38. #include <string.h>
  39.  
  40. ///////////////////////////////////////////////////////////////////
  41. // Constants and types for ARP module messages.
  42.  
  43. #include "OTARPModule.h"
  44.  
  45. ///////////////////////////////////////////////////////////////////
  46. // Prototypes for our high-level interface to ARP.
  47.  
  48. #include "ARPerations.h"
  49.  
  50. ///////////////////////////////////////////////////////////////////
  51.  
  52. // Define a structure for holding a standard hardware address,
  53. // ie a 6 byte Ethernet address.
  54.  
  55. struct HardwareAddress {
  56.     UInt8    fHardwareAddress[6];
  57. };
  58. typedef struct HardwareAddress HardwareAddress;
  59.  
  60. ///////////////////////////////////////////////////////////////////
  61.  
  62. // Define constants for all the default address and such that we
  63. // assume if you enter a blank field.
  64.  
  65. static char             kDefaultInterfaceName[] = "pci1011,140";
  66. static HardwareAddress     kDefaultHardwareAddress = { 0x00, 0x05, 0x02, 0xBC, 0xC8, 0x4F };
  67. static InetHost         kDefaultIPAddress = ( (17L << 24) || (203L << 16) || (21L << 8) || 98);
  68. static char             kDefaultInterfaceConfig[] = "enet";
  69.  
  70. ///////////////////////////////////////////////////////////////////
  71.  
  72. // Routines for reading and writing various address types.
  73.  
  74. static void GetHardwareAddress(HardwareAddress *hwAddr)
  75.     // Prompt the user for a hardware address.
  76. {
  77.     unsigned int hw0, hw1, hw2, hw3, hw4, hw5;
  78.     int result;
  79.     char tmpStr[256];
  80.     
  81.     printf("Enter a hardware address:\n");
  82.     tmpStr[0] = 0;
  83.     gets(tmpStr);
  84.     printf("“%s”\n", tmpStr);
  85.     result = sscanf(tmpStr, "%x:%x:%x:%x:%x:%x", &hw0, &hw1, &hw2, &hw3, &hw4, &hw5);
  86.     
  87.     if (result != 6) {
  88.         printf("Wrong answer. Using default hardware address.\n");
  89.         *hwAddr = kDefaultHardwareAddress;
  90.     } else {
  91.         hwAddr->fHardwareAddress[0] = hw0;
  92.         hwAddr->fHardwareAddress[1] = hw1;
  93.         hwAddr->fHardwareAddress[2] = hw2;
  94.         hwAddr->fHardwareAddress[3] = hw3;
  95.         hwAddr->fHardwareAddress[4] = hw4;
  96.         hwAddr->fHardwareAddress[5] = hw5;
  97.     }
  98. }
  99.  
  100. static void HardwareAddressToString(HardwareAddress hwAddr, char *outputString)
  101.     // Convert a hardware address to a string suitable for printing.
  102. {
  103.     sprintf(outputString, "%02x:%02x:%02x:%02x:%02x:%02x", 
  104.         hwAddr.fHardwareAddress[0],
  105.         hwAddr.fHardwareAddress[1],
  106.         hwAddr.fHardwareAddress[2],
  107.         hwAddr.fHardwareAddress[3],
  108.         hwAddr.fHardwareAddress[4],
  109.         hwAddr.fHardwareAddress[5]
  110.         );
  111. }
  112.  
  113. static void GetInterfaceName(char *intfName)
  114.     // Prompt the user for an interface name.
  115. {
  116.     printf("Enter an ARP interface name (press return for “%s”):\n", kDefaultInterfaceName);
  117.     intfName[0] = 0;
  118.     gets(intfName);
  119.     if (intfName[0] == 0) {
  120.         strcpy(intfName, kDefaultInterfaceName);
  121.     }
  122. }
  123.  
  124. static void GetIPAddress(InetHost *ipAddr)
  125.     // Prompt the user for an IP address.
  126. {
  127.     char tmpStr[256];
  128.     unsigned int ip0, ip1, ip2, ip3;
  129.     int result;
  130.     
  131.     printf("Enter an IP address:\n");
  132.     tmpStr[0] = 0;
  133.     gets(tmpStr);
  134.     result = sscanf(tmpStr, "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3);
  135.     
  136.     if (result != 4) {
  137.         printf("Wrong answer. Using default IP address.\n");
  138.         *ipAddr = kDefaultIPAddress;
  139.     } else {
  140.         *ipAddr = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;
  141.     }
  142. }
  143.  
  144. static void IPAddressToString(InetHost ipAddr, char *outputString)
  145.     // Convert an IP address to a string suitable for printing.
  146. {
  147.     sprintf(outputString, "%d.%d.%d.%d", 
  148.         (ipAddr >> 24) & 0x0ff,
  149.         (ipAddr >> 16) & 0x0ff,
  150.         (ipAddr >> 8)  & 0x0ff,
  151.         (ipAddr >> 0)  & 0x0ff
  152.         );
  153. }
  154.  
  155. static void GetFlag(char *flagName, UInt32 flagValue, UInt32 *flags)
  156.     // Prompt the user for a flag.  The flagName is the user-visible
  157.     // name of the flag.  If the user types anything other than
  158.     // return or "n", flagVlaue is ORed into the flags variable.
  159. {
  160.     char tmpStr[256];
  161.     
  162.     printf("%s? (y/n)\n", flagName);
  163.     gets(tmpStr);
  164.     if ( tmpStr[0] != 0 && tmpStr[0] != 'n' && tmpStr[0] != 'N') {
  165.         (*flags) |= flagValue;
  166.     }
  167. }
  168.  
  169. static void PrintFlag(char *flagName, UInt32 flagMask, UInt32 flags)
  170.     // Print a flag.
  171. {
  172.     if ( (flags & flagMask) != 0 ) {
  173.         printf("%s ", flagName);
  174.     }
  175. }
  176.  
  177. ///////////////////////////////////////////////////////////////////
  178.  
  179. static OSStatus DoARPGetCacheReport(void)
  180.     // Call through to the equivalent ARPerations routine
  181.     // and then print the results.
  182. {
  183.     OSStatus err;
  184.     Handle cacheReportHandle;
  185.     char zero;
  186.     
  187.     printf("DoARPGetCacheReport\n");
  188.     cacheReportHandle = NewHandle(0);
  189.     err = MemError();
  190.     if (err == noErr) {
  191.         err = ARPGetCacheReport(cacheReportHandle);
  192.         if (err == noErr) {
  193.             zero = 0;
  194.             err = PtrAndHand(&zero, cacheReportHandle, sizeof(zero));
  195.             if (err == noErr) {
  196.                 HLock(cacheReportHandle);
  197.                 printf("%s\n\n", *cacheReportHandle);
  198.             }
  199.         }
  200.         DisposeHandle(cacheReportHandle);
  201.     }
  202.     printf("\n");
  203.     return (err);
  204. }
  205.  
  206. ///////////////////////////////////////////////////////////////////
  207.  
  208. static OSStatus DoARPAddEntry(void)
  209.     // Prompt user for input and then call straight through
  210.     // to the equivalent ARPerations routine.
  211. {
  212.     OSStatus err;
  213.     char interfaceName[256];
  214.     InetHost ipAddr;
  215.     InetHost ipMask = 0xFFFFFFFF;
  216.     HardwareAddress hwAddr;
  217.     char ipAddrString[256];
  218.     char hwAddrString[256];
  219.     UInt32 flags;
  220.     
  221.     printf("DoARPAddEntry\n");
  222.     GetInterfaceName(interfaceName);
  223.     GetIPAddress(&ipAddr);
  224.     IPAddressToString(ipAddr, ipAddrString);
  225.     GetHardwareAddress(&hwAddr);
  226.     HardwareAddressToString(hwAddr, hwAddrString);
  227.     flags = 0;
  228.     GetFlag("PERM   ", ACE_F_PERMANENT, &flags);
  229.     GetFlag("PUBLISH", ACE_F_PUBLISH, &flags);
  230.     GetFlag("MAPPING", ACE_F_MAPPING, &flags);
  231.     
  232.     printf("Adding ARP cache entry for %s -> %s on “%s”.\n", ipAddrString, hwAddrString, interfaceName);
  233.     
  234.     err = ARPAddEntry(interfaceName, IP_ARP_PROTO_TYPE, flags, 
  235.                         &ipAddr, sizeof(InetHost), &ipMask, &hwAddr, sizeof(hwAddr));
  236.  
  237.     return (err);
  238. }
  239.  
  240. ///////////////////////////////////////////////////////////////////
  241.  
  242. static OSStatus DoARPDeleteEntry(void)
  243.     // Prompt user for input and then call straight through
  244.     // to the equivalent ARPerations routine.
  245. {
  246.     OSStatus err;
  247.     InetHost ipAddr;
  248.     char interfaceName[256];
  249.     char ipAddrString[256];
  250.     
  251.     printf("DoARPDeleteEntry\n");
  252.     GetInterfaceName(interfaceName);
  253.     GetIPAddress(&ipAddr);
  254.     IPAddressToString(ipAddr, ipAddrString);
  255.     
  256.     printf("Deleting ARP cache entry for %s on “%s”.\n", ipAddrString, interfaceName);
  257.     
  258.     err = ARPDeleteEntry(interfaceName, IP_ARP_PROTO_TYPE, &ipAddr, sizeof(InetHost));
  259.  
  260.     return (err);
  261. }
  262.  
  263. ///////////////////////////////////////////////////////////////////
  264.  
  265. static OSStatus DoARPCacheQuery(void)
  266.     // Prompt user for input, call through to the equivalent
  267.     // ARPerations routine, and then print the results.
  268. {
  269.     OSStatus err;
  270.     char interfaceName[256];
  271.     InetHost ipAddr;
  272.     HardwareAddress hwAddr;
  273.     char ipAddrString[256];
  274.     char hwAddrString[256];
  275.     UInt32 flags;
  276.     
  277.     printf("DoARPCacheQuery\n");
  278.     GetInterfaceName(interfaceName);
  279.     GetIPAddress(&ipAddr);
  280.     IPAddressToString(ipAddr, ipAddrString);
  281.     
  282.     printf("Lookup ARP cache entry for %s on “%s”.\n", ipAddrString, interfaceName);
  283.     
  284.     err = ARPCacheQuery(interfaceName,
  285.                         IP_ARP_PROTO_TYPE,
  286.                         &ipAddr, sizeof(InetHost),
  287.                         &hwAddr, sizeof(hwAddr), &flags);
  288.  
  289.     if (err == noErr) {
  290.         HardwareAddressToString(hwAddr, hwAddrString);
  291.         printf("Hardware address is %s.\n", hwAddrString);
  292.         printf("Flags are ");
  293.         PrintFlag("PERM", ACE_F_PERMANENT, flags);
  294.         PrintFlag("PUBLISH", ACE_F_PUBLISH, flags);
  295.         PrintFlag("DYING", ACE_F_DYING, flags);
  296.         PrintFlag("RESOLVED", ACE_F_RESOLVED, flags);
  297.         PrintFlag("MAPPING", ACE_F_MAPPING, flags);
  298.         printf("\n");
  299.     }
  300.  
  301.     return (err);
  302. }
  303.  
  304. ///////////////////////////////////////////////////////////////////
  305.  
  306. // This sample uses a big global array (gInterfacesWeBroughtUp) to store
  307. // the list of interfaces that we have brought up.   The top of this
  308. // array is defined by gMaxInterfaceIndex.  The array stores
  309. // the configuration string used to create the interface (so that
  310. // we can display it to the user) and the interfaceCookie returned
  311. // by ARPInterfaceUp (so we can pass it back to ARPInterfaceDown
  312. // to tear down the interface).
  313.  
  314. enum {
  315.     kNumberOfOurARPInterfaces = 10            // Obviously an arbitrary limit.
  316. };
  317.  
  318. struct InterfaceInfo {
  319.     UInt32 cookie;
  320.     char configString[256];
  321. };
  322. typedef struct InterfaceInfo InterfaceInfo;
  323.  
  324. static InterfaceInfo gInterfacesWeBroughtUp[kNumberOfOurARPInterfaces];
  325.  
  326. static SInt32 gMaxInterfaceIndex = -1;
  327.  
  328. static OSStatus DoARPPrintOurInterfaces(void)
  329.     // Print the list of ARP interfaces we have brought up.
  330. {
  331.     SInt32 interfaceIndex;
  332.     
  333.     printf("DoARPPrintOurInterfaces\n");
  334.     printf("Interfaces we brought up:\n");
  335.     for (interfaceIndex = 0; interfaceIndex <= gMaxInterfaceIndex; interfaceIndex++) {
  336.         printf("%2d -- %s\n",
  337.             interfaceIndex,
  338.             gInterfacesWeBroughtUp[interfaceIndex].configString
  339.             );
  340.     }
  341.     printf("\n");
  342.     return (noErr);
  343. }
  344.  
  345. static OSStatus DoARPInterfaceUp(void)
  346.     // Prompt user for input and then call through to ARPInterfaceUp
  347.     // to bring up the interface.  If this succeeds, record the
  348.     // interface in gInterfacesWeBroughtUp so we can tear it down
  349.     // again.
  350. {
  351.     OSStatus err;
  352.     
  353.     printf("DoARPInterfaceUp\n");
  354.     err = noErr;
  355.     if ( gMaxInterfaceIndex == (kNumberOfOurARPInterfaces - 1) ) {
  356.         err = -3;
  357.     }
  358.     if (err == noErr) {
  359.         printf("Enter the configuration string of the interface you want to bring up:\n");
  360.         gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString[0] = 0;
  361.         gets(gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString);
  362.         if ( gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString[0] == 0 ) {
  363.             OTStrCopy(gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString, kDefaultInterfaceConfig);
  364.         }
  365.     }
  366.     if (err == noErr) {
  367.         err = ARPInterfaceUp(gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString,
  368.                         &gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].cookie); 
  369.     }
  370.     if (err == noErr) {
  371.         gMaxInterfaceIndex += 1;
  372.     }
  373.     
  374.     return (err);
  375. }
  376.  
  377. static OSStatus DoARPInterfaceDown(void)
  378.     // Prompt user for the numeric index of the interface they 
  379.     // want to tear down, and then call through to ARPInterfaceDown
  380.     // to tear it down.  Afterwards, delete the torn down element from
  381.     // the gInterfacesWeBroughtUp array
  382. {
  383.     OSStatus err;
  384.     SInt32 interfaceIndex;
  385.     char tmpStr[256];
  386.     
  387.     printf("DoARPInterfaceDown\n");
  388.     (void) DoARPPrintOurInterfaces();
  389.     printf("Enter an interface to take down:\n");
  390.     tmpStr[0] = 0;
  391.     gets(tmpStr);
  392.     err = noErr;
  393.     if ( sscanf(tmpStr, "%ld", &interfaceIndex) != 1 ) {
  394.         err = -1;
  395.     }
  396.     if (err == noErr) {
  397.         if ( (interfaceIndex < 0) || (interfaceIndex > gMaxInterfaceIndex) ) {
  398.             err = -2;
  399.         }
  400.     }
  401.     if (err == noErr) {
  402.         err = ARPInterfaceDown(gInterfacesWeBroughtUp[interfaceIndex].cookie);
  403.     }
  404.     if (err == noErr) {
  405.         gInterfacesWeBroughtUp[interfaceIndex] = gInterfacesWeBroughtUp[gMaxInterfaceIndex];
  406.         gMaxInterfaceIndex -= 1;
  407.     }
  408.     
  409.     return (err);
  410. }
  411.  
  412. ///////////////////////////////////////////////////////////////////
  413.  
  414. static OSStatus DoPrintCommandHelp(void)
  415.     // Print the current list of commands.
  416. {
  417.     printf("DoPrintCommandHelp\n");
  418.     printf("?) Prints this help.\n");
  419.     printf("\n");
  420.     printf("p) Print contents of ARP cache.\n");
  421.     printf("a) Add an ARP cache entry.\n");
  422.     printf("k) Delete an ARP cache entry.\n");
  423.     printf("l) Lookup an ARP cache entry.\n");
  424.     printf("\n");
  425.     printf("i) See the ARP interfaces we have brought up.\n");
  426.     printf("u) Bring up a new ARP interface.\n");
  427.     printf("d) Tear down an ARP interface.\n");
  428.     printf("\n");
  429.     printf("q) Quit.\n");
  430.     
  431.     return (noErr);
  432. }
  433.  
  434. ///////////////////////////////////////////////////////////////////
  435.  
  436. void main(void)
  437. {
  438.     OSStatus err;
  439.     char commandStr[256];
  440.     Boolean quitNow;
  441.         
  442.     printf("ARPSample -- A poor man's ARPing tool.\n");
  443.     
  444.     err = InitOpenTransport();
  445.     
  446.     if (err == noErr) {
  447.  
  448.         quitNow = false;
  449.         (void) DoPrintCommandHelp();
  450.         
  451.         // Welcome to the command loop.  Get a string from the user
  452.         // and use the first letter to dispatch to the relevant
  453.         // subroutine.
  454.         
  455.         do {
  456.             printf("Enter a letter corresponding to a command.\n");
  457.  
  458.             err = noErr;
  459.             gets(commandStr);
  460.             switch (commandStr[0]) {
  461.                 case '?':
  462.                     err = DoPrintCommandHelp();
  463.                     break;
  464.                 case 'p':
  465.                     err = DoARPGetCacheReport();
  466.                     break;
  467.                 case 'a':
  468.                     err = DoARPAddEntry();
  469.                     break;
  470.                 case 'k':
  471.                     err = DoARPDeleteEntry();
  472.                     break;
  473.                 case 'l':
  474.                     err = DoARPCacheQuery();
  475.                     break;
  476.                 case 'i':
  477.                     err = DoARPPrintOurInterfaces();
  478.                     break;
  479.                 case 'u':
  480.                     err = DoARPInterfaceUp();
  481.                     break;
  482.                 case 'd':
  483.                     err = DoARPInterfaceDown();
  484.                     break;
  485.                 case 'q':
  486.                     quitNow = true;
  487.                     break;
  488.                 case '\n':
  489.                     break;
  490.                 default:
  491.                     printf("Huh? “%s”\n", commandStr);
  492.                     break;
  493.             }
  494.             if (err != noErr) {
  495.                 printf("Error %ld.\n", err);
  496.             }
  497.         } while ( ! quitNow );    
  498.  
  499.         CloseOpenTransport();
  500.     }
  501.     
  502.     if (err == noErr) {
  503.         printf("Success.\n");
  504.     } else {
  505.         printf("Failed with error %d.\n", err);
  506.     }
  507.     printf("Done.  Press command-Q to Quit.\n");
  508. }
  509.  
  510.